package com.kyrie.lib_sys.annotation.logAnnotation;

import com.google.gson.Gson;
import com.kyrie.lib_sys.application.syslogApplys.LogRecordService;
import com.kyrie.lib_sys.context.RequestHolder;
import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;



import java.lang.reflect.Method;
import java.util.Date;

/**
 * 操作日志切面
 */
@Aspect
@Component
public class OperateLogAspect {

    @Autowired
    private LogRecordService logRecordService;

    /**
     * 定义切点：所有被@OperationLog注解的方法
     */
    @Around("@annotation(operationLog)")
    public Object around(ProceedingJoinPoint joinPoint, OperationLog operationLog) throws Throwable {
        // 1. 方法执行前：记录开始时间和参数
        long startTime = System.currentTimeMillis();
        Object[] args = joinPoint.getArgs();

        // 2. 执行目标方法
        Object result = null;
        Throwable exception = null;

        try {
            result = joinPoint.proceed();
            return result;
        } catch (Throwable e) {
            exception = e;
            throw e;
        } finally {
            // 3. 方法执行后：记录日志（无论成功或失败）
            long endTime = System.currentTimeMillis();
            long costTime = endTime - startTime;

            recordLog(joinPoint, operationLog, args, result, exception, costTime);
        }
    }

    /**
     * 记录操作日志
     */
    private void recordLog(ProceedingJoinPoint joinPoint, OperationLog operationLog,
                           Object[] args, Object result, Throwable exception, long costTime) {
        try {
            // 获取方法信息
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            String className = joinPoint.getTarget().getClass().getName();
            String methodName = method.getName();

            // 构建日志信息
            LogRecord logRecord = new LogRecord();
            logRecord.setModule(operationLog.module());
            logRecord.setOperationType(operationLog.type().name());
            logRecord.setDescription(operationLog.description());
            logRecord.setClassName(className);
            logRecord.setMethodName(methodName);
            logRecord.setCostTime(costTime);
            logRecord.setStatus(exception == null ? "SUCCESS" : "FAILED");
            logRecord.setCreateTime(new Date());

            // 记录参数（如果需要）
            if (operationLog.recordParams()) {
                logRecord.setParams(new Gson().toJson(args));
            }

            // 记录结果（如果需要且成功）
            if (operationLog.recordResult() && exception == null) {
                logRecord.setResult(new Gson().toJson(result));
            }

            // 记录异常信息（如果有）
            if (exception != null) {
                logRecord.setErrorMsg(exception.getMessage());
            }

            // 获取当前用户信息（可以根据threadlocal上下文中获取）
            setUserInfo(logRecord);

            // 获取请求信息（可以根据interceptor拦截器通过上下文获取）
            setRequestInfo(logRecord);

            // 异步保存日志到数据库
            asyncSaveLog(logRecord);

        } catch (Exception e) {
            // 日志记录本身不能影响业务逻辑
            System.err.println("记录操作日志失败: " + e.getMessage());
        }
    }

    /**
     * 设置用户信息(自定义handler上下文)
     */
    private void setUserInfo(LogRecord logRecord) {
        String currentUser = RequestHolder.getCurrentUser();
        if (currentUser != null) {
            logRecord.setOperator(currentUser);
        } else {
            logRecord.setOperator("system");
        }
    }

    /**
     * 设置请求信息
     */
    private void setRequestInfo(LogRecord logRecord) {
        HttpServletRequest request = RequestHolder.getCurrentRequest();
        if (request != null) {
            logRecord.setRequestIp(request.getRemoteAddr());
            logRecord.setRequestUrl(request.getRequestURI());
        } else {
            logRecord.setRequestIp("127.0.0.1");
            logRecord.setRequestUrl("/unknown");
        }
    }

    /**
     * 异步保存日志
     */
    @Async
    protected void asyncSaveLog(LogRecord logRecord) {
        // 使用异步线程或消息队列保存日志，避免影响主业务流程
        logRecordService.saveLog(logRecord);
    }

}
